package com.sw.study.presisence.sqlsession.sessionfactory.impl;

import com.sw.study.common.exception.ExceptionConstants;
import com.sw.study.common.exception.sql.SqlResultException;
import com.sw.study.presisence.executor.DefaultExecutor;
import com.sw.study.presisence.executor.Executor;
import com.sw.study.presisence.pojo.Configuration;
import com.sw.study.presisence.pojo.MappedStatement;
import com.sw.study.presisence.sqlsession.sessionfactory.SqlSession;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Created by sw on 2020/3/25.
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {
        Executor executor=new DefaultExecutor();
        MappedStatement mappedStatement= configuration.getMappedStatementMap().get(statementId);
        List<Object> objects= executor.query(configuration,mappedStatement,params);
        return (List<E>) objects;
    }

    /**
     *
     * @param statementId
     * @param params
     * @return
     */
    @Override
    public int execute(String statementId, Object... params) throws Exception {
        Executor executor=new DefaultExecutor();
        MappedStatement mappedStatement= configuration.getMappedStatementMap().get(statementId);
        return executor.execute(configuration,mappedStatement,params);
    }


    /**
     * 查询单个
     *
     * @param statementId
     * @param params
     * @return
     */
    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        List<Object> objects= selectList(statementId,params);
        if(null==objects || objects.size()==0){
            return null;
        }
        if(objects.size()>1){
            throw  new SqlResultException(ExceptionConstants.SQLRESULT,"get one but return ");
        }
        return (T) objects.get(0);
    }

    /**
     * @param mapperClass
     * @return
     */
    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        /**
         * 动态代理实现
         */
        Object proxyClass=Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(),new Class[]{mapperClass},new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /**
                 * 最终还是要执行jdbc
                 */
                /**
                 * 方法名
                 */
                String methodName=method.getName();
                /**
                 * 根据方法名 拿到类全限定名
                 */
                String className=method.getDeclaringClass().getName();
                String key=className+"."+methodName;
                /**
                 * 参数：params  --》args
                 */
               // MappedStatement mappedStatement=configuration.getMappedStatementMap().get(key);
                /**
                 * 获取方法返回值类型
                 *
                 */
               // Type geneType=method.getAnnotatedReturnType().getType();//个人定义
                Type geneType=method.getGenericReturnType();
                if( geneType instanceof ParameterizedType){
                    return selectList(key,args);
                }else if(geneType.getTypeName().equals("int")){
                    return  execute(key,args);
                }else {
                    return selectOne(key,args);

                }
            }
        });
        return (T) proxyClass;
    }




}